package tk.mybatis.springboot.share.util;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;


/**
 * 发送post和get请求 title:TP form:Mr_xing
 *
 * @author Xing
 * @date 2016年3月18日 上午9:09:26
 */
public class HttpUtil {

	private static final Logger logger = Logger.getLogger(HttpUtil.class);

	/**
	 * 根据url和参数map来发送post请求
	 *
	 * @param url
	 * @param map
	 * @return
	 */
	public static String sendPost(String url, Map<String, String> map) {
		String param = getParamByMap(map);
		// System.out.println("发送了一个post请求，url:" + url + ",参数为：" + param);
		return sendPost(url, param, null);
	}

	/**
	 * 发送post请求
	 * @param url 地址
	 * @param param_map 参数 
	 * @param request_map 与服务端约定的RequestProperty参数 键值对形式
	 * @return
	 */
	public static String sendPost(String url, Map<String, String> param_map, Map<String, String> request_map) {

		String param = getParamByMap(param_map);
		return sendPost(url, param, request_map);
	}

	/**
	 * 根据url和参数map来发送get请求
	 *
	 * @param url
	 * @param map
	 * @return
	 */
	public static String sendGet(String url, Map<String, String> map) {
		String str = getParamByMap(url, map);
		return sendGet(str);
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		//		logger.info("post请求:" + url + ",参数:" + param);
		return sendPost(url, param, null);
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数。(任意字符串，json、xml均可，直接写入参数)
	  * @param map  与服务端约定的RequestProperty参数 键值对形式
	  * 
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param, Map<String, String> map) {
		Date start = new Date();
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

			//参数拼接
			if (map != null && map.size() > 0) {
				Set<String> keys = map.keySet();
				for (String str : keys) {
					String val = map.get(str);
					conn.setRequestProperty(str, val);
				}
			}

			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 不要缓存
			conn.setUseCaches(false);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			Date end = new Date();
			logger.info("post请求:" + url + ",参数:" + param + "<========耗时:" + (end.getTime() - start.getTime()) + "毫秒=========>返回码:" + result);
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}

		return result;
	}

	/**
	 * 根据传过来的URL得到反馈地址，发送get请求
	 *
	 * @param service
	 * @return
	 */
	public static String sendGet(String service) {
		Date start = new Date();
		//		log.info("get请求:" + service);
		//		System.out.println(service);
		StringBuilder json = new StringBuilder();
		try {
			URL oracle = new URL(service);
			URLConnection yc = oracle.openConnection();
			// 不要缓存
			yc.setUseCaches(false);
			BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
			String inputLine = null;
			while ((inputLine = in.readLine()) != null) {
				json.append(inputLine);
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		Date end = new Date();
		logger.info("get请求:" + service + "<========耗时:" + (end.getTime() - start.getTime()) + "毫秒=========>返回码:" + json.toString());
		// System.out.println(json.toString());
		return json.toString();
	}

	/**
	 * 通过url和map来拼接最终url
	 *
	 * @param url
	 * @param map
	 * @return
	 */
	public static String getParamByMap(String url, Map<String, String> map) {
		// 保证map里面至少有一个值
		if (map != null && map.keySet() != null && map.keySet().size() != 0) {
			url += "?";
			for (String key : map.keySet()) {
				url += key + "=" + map.get(key) + "&";
			}
			url = url.substring(0, url.length() - 1);
		}
		return url;
	}

	/**
	 * 通过url和map来拼接最终url
	 *
	 * @param url
	 * @param map
	 * @return
	 */
	public static String getParamByMap(Map<String, String> map) {
		String url = "";
		// 保证map里面至少有一个值
		if (map != null && map.keySet() != null && map.keySet().size() != 0) {
			for (String key : map.keySet()) {
				url += key + "=" + map.get(key) + "&";
			}
			url = url.substring(0, url.length() - 1);
		}
		return url;
	}



	/**
	 * 发送get请求，根据ip得到地址，选用新浪的api,得到的json格式为
	 * {"ret":1,"start":-1,"end":-1,"country":"\u4e2d\u56fd"
	 * ,"province":"\u56db\u5ddd"
	 * ,"city":"\u6210\u90fd","district":"","isp":"","type":"","desc":""}
	 * country国家，province省，city城市，需要进行unicode编码
	 *
	 * @param ip
	 * @return
	 */
	//	public static JSONObject getAddressByIP(String ip) {
	//		JSONObject json = new JSONObject();
	//		Map<String, String> map = new HashMap<String, String>();
	//		map.put("format", "json");
	//		map.put("ip", ip);
	//
	//		String msg = sendGet("http://int.dpool.sina.com.cn/iplookup/iplookup.php", map);
	//		json = JSONObject.fromObject(msg);
	//		return json;
	//	}

	/**
	 * 根据ip得并返回中文地址
	 *
	 * @param ip
	 * @return
	 */
	//	public static String getAddressAllByIP(String ip) {
	//		if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
	//			return "";
	//		}
	//		JSONObject json = new JSONObject();
	//		json = getAddressByIP(ip);
	//		String msg = "";
	//		try {
	//			String add = json.getString("country") + "_" + json.getString("province") + "_" + json.getString("city") + "_";
	//			add = StringUtils.decodeUnicode(add);
	//			msg = add;
	//		} catch (Exception e) {
	//
	//		}
	//
	//		return msg;
	//	}
	//

	/**
	 * 向一个url上传文件，如果指定模拟post的信息，请传过来，测试(微信上传多媒体文件)
	 * @param url 目标地址
	 * @param param 参数，将写在参数里面
	 * @param foots 底部文件，没有则传空
	 * @param con_map 这个是请求头验证信息，可以不传
	 * @param file 文件信息
	 * @return
	 */
	public static String sendPost(String url, String param, String foots, Map<String, String> con_map, File file) {
		Date start = new Date();
		DataInputStream in = null;
		String result = "";
		OutputStream out = null;
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			conn.setDoInput(true);//设置输入
			conn.setDoOutput(true);//设置输出
			conn.setUseCaches(false); // post方式不能使用缓存  

			// 动态设置head信息
			if (con_map != null && con_map.size() > 0) {
				Set<String> keys = con_map.keySet();
				for (String str : keys) {
					String val = con_map.get(str);
					conn.setRequestProperty(str, val);
				}
			}

			// 获得输出流  
			out = new DataOutputStream(conn.getOutputStream());
			// 输出表头  
			byte[] head = param.getBytes("utf-8");
			out.write(head);

			// 文件正文部分  
			// 把文件已流文件的方式 推入到url中  
			if (null != file) {
				in = new DataInputStream(new FileInputStream(file));
				int bytes = 0;
				byte[] bufferOut = new byte[1024];
				while ((bytes = in.read(bufferOut)) != -1) {
					out.write(bufferOut, 0, bytes);
				}
			}

			// 结尾部分  
			if (StringUtils.isNotEmpty(foots)) {
				byte[] foot = foots.getBytes("utf-8");// 定义最后数据分隔线  
				out.write(foot);
			}

			out.flush();

			// 定义BufferedReader输入流来读取URL的响应  
			StringBuffer buffer = new StringBuffer();
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				buffer.append(line);
			}

			result = buffer.toString();
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (null != in) {
					in.close();
				}
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			Date end = new Date();
			logger.info("post请求:" + url + ",参数:" + param + "<========耗时:" + (end.getTime() - start.getTime()) + "毫秒=========>返回码:" + result);
		}

		return result;
	}

	public void senkr() {
		for (int i = 0; i < 10; i++) {
			try {
				// Thread.sleep((int) (1000 + Math.random() * (100)));
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// 每秒1个
			String aa = sendGet("http://www./", null);
			System.out.println("第" + i + "个:" + aa);
		}

	}

	public static void main(String[] args) {
		String str = HttpUtil.sendGet("http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=teapic.com");
		//		send.senkr();
		System.out.println(str);
		System.out.println("ok");
	}

}

